﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using NLog;

namespace hello.csharp.helper
{
    public class LogFileParseHelper
    {
        private readonly ILogger _logger = LogManager.GetCurrentClassLogger();

        public const string ALL_LOGS = "all-logs";
        public const string OWN_LOGS = "own-logs";

        public object BuildSimpleOwnLogTable()
        {
            return ReadLogFile(OWN_LOGS);
        }

        public object BuildSimpleAllLogTable()
        {
            return ReadLogFile(ALL_LOGS);
        }

        private object ReadLogFile(string file)
        {
            var i = 0;
            var list = new List<string>();
            var path = BuildLogPath(file);
            using (StreamReader sr = new StreamReader(path, Encoding.Default))
            {
                string line;
                while ((line = sr.ReadLine()) != null && i < 1000)
                {
                    list.Add(line);
                    i++;
                }
            }
            var result = ParseLogArray(list);
            _logger.Trace($"{file}共计{result.Count}行日志,{path}");
            return result;
        }

        protected string BuildLogPath(string mid)
        {
            var m = DateTime.Now.ToString("yyyyMM");
            var d = DateTime.Now.ToString("yyyy-MM-dd");
            var path = Path.Combine(GetLogPath(),"Logs", $@"{m}\", $@"{mid}-{d}.log");
            return path;
        }

        public static string GetLogPath()
        {
            //在项目属性中手工定义的输出文件
            var location = Assembly.GetEntryAssembly().Location;
            var dir = new DirectoryInfo(location);
            var dirName = Directory.GetDirectoryRoot(location);
            if (dir.Parent != null)
                dirName = dir.Parent.FullName;
            return dirName;
        }

        public static List<LogObj> ParseLogArray(List<string> array)
        {
            if (array == null || array.Count <= 0)
                return new List<LogObj>(0);
            var result = new List<LogObj>();
            for (int i = 0; i < array.Count; i++)
            {
                var logLine = array[i];
                if (logLine.Length < 24)
                    continue;
                var sub = logLine.Substring(0, 24);
                if (DateTime.TryParse(sub, out var now))
                {
                    var obj = new LogObj();
                    var s = logLine.Split('|');
                    obj.Time = now.ToString("HH:mm:ss.ffff");
                    obj.EventId = s[1].Trim(' ');
                    obj.Level = s[2].ToLower().Trim(' ');
                    obj.Message = s[4];
                    if (s.Length > 5)
                    {
                        obj.Url = s[5].Substring(5).Trim(' ');
                        obj.Action = s[6].Substring(7).Trim(' ');
                        obj.Method = s[7].Trim(' ');
                    }
                    result.Insert(0, obj);
                }
                else
                {
                    result[0].Message = $"{result[0].Message}\r\n<br />　　　{logLine.Trim(' ')}";
                }
            }

            return result;
        }
    }

    public class LogObj
    {
        public string Time { get; set; }
        public string EventId { get; set; }
        public string Level { get; set; }
        public string Method { get; set; }
        public string Url { get; set; }
        public string Action { get; set; }
        public string Message { get; set; }

        #region Overrides of Object

        /// <inheritdoc />
        public override string ToString()
        {
            return $"{Time},{Level},{Message}";
        }

        #endregion
    }
}
